#define MAX_COMMAND_SZ 256

#include "consola.h"
#include "Utiles.h"

int 	sockConsola;
char 	*command;

#define SOCK_PATH "connect_socket"

int main()
{
	//signal(SIGINT, finShell);

	char buff[1024], buff2[1024]; //, buf[8192],md5Dir[256];
	char *cp, *cp2;
	char cvStringConsola[257];
	int len;
	struct sockaddr_un remote;
	int comandoInvalido;
	ST_NIPC	stCabecera;
	//char pedido[256];
	int i, cantenviado;
	//char sectorPipe[256];
	//int tmpRandom, tmpI;
	char *path;
	ST_RESPUESTA respuesta;
	//pthread_t threadRespuestas;
	float tiempo = 0;
	int32_t sectorInicial, sectorFinal, sectorActual, sectorProximo;
	ST_CHS actual;

	signal(SIGINT, FinConsola);

	path=(char *)malloc(sizeof(char)*500);
	len = cargarConfiguracion();
	iniciarLog( "consolaLog.txt" );
	log("consolaLog.txt", "PPD", "INFO", "Inicia el proceso PPD");
	system("clear");

	stPConsola.sectoresTotales = (int)stPConsola.iCilindro * (int)stPConsola.iSector;
	//7200 rev ---- 1min = 60secs = 60000ms
	//1 rev --- 60000/7200ms = 8ms aprox
	tiempo = 60000/(int)stPConsola.iRPM;
	stPConsola.tiempoEntreSectores = tiempo / stPConsola.sectoresTotales;

	sprintf(path, "%s/connect_socket", stPConsola.szPathPPD);
	//printf("PathConfig: %s\n", stPConsola.szPathPPD);
	//printf("Path: %s\n", path);

	printf("****************************************************************************\n");
	printf("\t\t\tCONSOLA DEL PPD %s\n", stPConsola.szIdPPD);
	printf("****************************************************************************\n\n");

	if ((sockConsola = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
	{
		perror ("ERROR");
        return 1;
	}//else
		//printf ("INFO: cree el socket\n");

	remote.sun_family = AF_UNIX;
	strcpy(remote.sun_path, path);
	len = strlen(remote.sun_path) + sizeof(remote.sun_family);
	if (connect(sockConsola, (struct sockaddr *)&remote, len) == -1) {
		perror("Connect");
		return 1;
	}

	/* Envio solicitud de conexion */
	stCabecera.ucType = HANDSHAKE;
	stCabecera.lPayload = 0;

	if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
		log( "consolaLog.txt", "PPD", "ERROR", "Error al querer enviar handshake");
	//else
		//printf("Envie handshake\n");

	if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 ) {
			close( sockConsola );
			log( "consolaLog.txt", "PPD", "ERROR","Al recibir respuesta del Hand Shake");
			return 1;
		}//else
			//printf("Recibi respuesta del handshake\n");

	switch ( stCabecera.ucType ) {
			case FAIL:
				log( "consolaLog.txt", "PPD", "ERROR","Conexion del PPD rechazada");
				printf("Conexion rechazada\n");
				break;
			case PPD:
				log( "consolaLog.txt", "PPD", "INFO","Conexion con PPD establecida");
				//printf("Conexion con PPD establecida\n");
				break;
	}
	//pthread_create(&threadRespuestas, NULL, (void *) &ManejoRespuestas, NULL);
	while (1)
	{
		printf("\nIngrese una petición: \n");
		fgets(cvStringConsola, 256, stdin);
		if (cvStringConsola[strlen(cvStringConsola) - 1] == '\n')
			cvStringConsola[strlen(cvStringConsola) - 1] = '\0';
		comandoInvalido = 0;
		cp = strtok(cvStringConsola, " ");
		if (strcmp(cp, "info")==0){
			//printf("\nPosicion actual del cabezal\n");
			comandoInvalido = 1;
			//Cargo datos en estructura para enviar al PPD
			stCabecera.ucType = INFO;
			stCabecera.lPayload = 0;
			memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
			if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de Información de cabezal");
			else
				log( "consolaLog.txt", "PPD", "INFO", "Envie petición de Información de cabezal");

			//memset(stCabecera.szPayload, 0, sizeof(stCabecera.szPayload));

			if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir petición de Información de cabezal");
			else
				log( "consolaLog.txt", "PPD", "INFO", "Recepción correcta de Información de cabezal");

			actual = LBAtoCHS(stCabecera.sector);
			printf("\nPosicion actual del cabezal: %d:%d\n", actual.cilindro, actual.sector);

		}else if (strcmp(cp, "help")==0)
		{
			comandoInvalido = 1;
			printf("Comandos Disponibles:\ninfo \nclean <sector inicial> <sector final>\ntrace <lista de sectores>\ntiempoLectura <tiempo(ms)>\ntiempoEscritura <tiempo(ms)>\nhelp\nexit\n\n");
		}else if (strcmp(cp,"exit")==0)
		{
			comandoInvalido = 1;
			FinConsola();
		}else if (strcmp(cp, "clean")==0)
		{
			printf("\Limpieza de sectores:\n");
			comandoInvalido = 1;

			//Cargo datos en estructura para enviar al PPD


			memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
			cp = strtok(NULL, " ");
			sectorInicial = atoi(cp);
			cp2 = strtok(NULL, " ");
			sectorFinal = atoi(cp2);
			if ((sectorInicial >= 0) && (sectorFinal >= 0) && (sectorFinal <= stPConsola.sectoresTotales)&& (sectorInicial <= stPConsola.sectoresTotales))
			{
				for (i=sectorInicial; sectorFinal >= i; i ++ )
				{
					stCabecera.ucType = CLEAN;
					//strcpy(stCabecera.szPayload, "");
					//memset(stCabecera.szPayload, '\0', sizeof(stCabecera.szPayload));
					stCabecera.sector = i;
					//memset(respuesta.buffer, 0, sizeof(ST_SECTOR));
					memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
					stCabecera.lPayload = sizeof(stCabecera.buffer);

					if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de limpieza de sectores");
					else
						log( "consolaLog.txt", "PPD", "INFO", "Envie petición de limpieza de sectores");

					if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir confirmacion de limpieza de sectores");
					else
						log( "consolaLog.txt", "PPD", "INFO", "Recepción de confirmacion de limpieza de sectores");

				}
				if (stCabecera.ucType == WRITESECTOROK)
					printf("Los sectores solicitados fueron borrados correctamente\n");
				else
					printf("Error al intentar borrar los sectores solicitados\n");
			}else
				comandoInvalido = 0;
		}else if (strcmp(cp, "trace")==0)
		{
			printf("\Listado de trazo de sectores pedidos:\n");
			comandoInvalido = 1;
			//ENVIAR LISTA DE TRAZOS DE UNA
			cp = strtok(NULL, " ");
			while(cp!=NULL)
			{

				sectorInicial = atoi(cp);
				if (sectorInicial > stPConsola.sectoresTotales)
				{
					printf("El sector %d ingresado es invalido\n", sectorInicial);
					cp = strtok(NULL, " ");
				}
				else
				{
					stCabecera.ucType = INFO;
					stCabecera.lPayload = 0;
					memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
					if((cantenviado=send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL)) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de Información de cabezal");
					else
						log( "consolaLog.txt", "PPD", "INFO", "Envie petición de Información de cabezal");

					//memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
					//printf("Enviado %d y tamanio %d\n", cantenviado, sizeof(ST_NIPC));
					//printf("Envie peticion de INFO, esperando respuesta\n");

					if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir petición de Información de cabezal");
					else
						log( "consolaLog.txt", "PPD", "INFO", "Recepción correcta de Información de cabezal");

					sectorActual = stCabecera.sector;

					//printf("Recibi respuesta de info, sector actual %d\n", sectorActual);

					stCabecera.ucType = TRACE;
					//strcpy(stCabecera.lPayload, "");

					stCabecera.sector = sectorInicial;
					memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
					//printf("Sector pedido: %d\n", sectorInicial);
					stCabecera.lPayload = sizeof(stCabecera.buffer);

					if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de TRACE");
					else
						log( "consolaLog.txt", "PPD", "INFO", "Envie petición de TRACE");

					//printf("Envie pedido de TRACE, esperando respuesta\n");

					if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
						log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir primera respuesta del TRACE");

					//printf("recibi rta de pedido de TRACE\n");
					//else
					//log( "consolaLog.txt", "PPD", "INFO", "Recepción de confirmacion de TRACE");


					//cp2=strtok(stCabecera.szPayload, "|");
					//stPConsola.iSectorActual=atoi(cp2);
					//printf("entre del trazo\n");
					imprimoTrazo(sectorActual, sectorInicial, stCabecera.sector);
					//printf("Proximo sector: %d\n", respuesta.sector);
					//printf("sali del trazo\n");
					cp = strtok(NULL, " ");

				}
				//sectorInicial = atoi(cp);
				//sprintf(stCabecera.szPayload,"%d|", sectorInicial);
				//printf("Sector pedido: %s\n", cp);
			}

		}else if (strcmp(cp, "write")==0)
		{
			printf("\Escribir en disco:\n");
			comandoInvalido = 1;
			//ENVIAR LISTA DE TRAZOS DE UNA
			stCabecera.ucType = WRITESECTOR;
			cp = strtok(NULL, " ");
			stCabecera.sector = atoi(cp);
			//sprintf(buff,"%s|", cp);
			cp = strtok(NULL, " ");
			sprintf(buff2,"%s|", cp);
			//sprintf(stCabecera.szPayload, "%s%s", buff, buff2);
			memcpy(stCabecera.buffer, buff2, sizeof(ST_SECTOR));
			//printf("Solicitud write %s\n", stCabecera.szPayload);
			stCabecera.lPayload = strlen(stCabecera.buffer);

			if(send(sockConsola, &stCabecera, sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de WRITESECTOR");
			else
				log( "consolaLog.txt", "PPD", "INFO", "Envie petición de WRITESECTOR");

			if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir confirmacion de WRITESECTOR");
			else
				log( "consolaLog.txt", "PPD", "INFO", "Recepción de confirmacion de WRITESECTOR");

			if (stCabecera.ucType==WRITESECTOROK)
				printf("Escritura realizada con exito\n");
			else
				printf("Escritura fallida\n");

		}else if (strcmp(cp, "read")==0)
		{
			printf("\Lectura en disco:\n");
			comandoInvalido = 1;
			//ENVIAR LISTA DE TRAZOS DE UNA
			stCabecera.ucType = GETSECTOR;
			cp = strtok(NULL, " ");
			printf("Sector pedido: %s\n", cp);
			//sprintf(stCabecera.szPayload,"%s|", cp);
			stCabecera.sector = atoi(cp);
			//printf("Sector pedido: %s\n", stCabecera.szPayload);
			memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
			stCabecera.lPayload = strlen(stCabecera.buffer);

			if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de GETSECTOR");
			else
				log( "consolaLog.txt", "PPD", "INFO", "Envie petición de GETSECTOR");

			if( recv( sockConsola, (void *) &stCabecera, sizeof(ST_NIPC), MSG_WAITALL) < 0 )
				log( "consolaLog.txt", "PPD", "ERROR", "Error al recibir primera respuesta del TRACE");

			if (stCabecera.ucType==RTASECTOR)
			{
				printf("Lectura realizada del sector: %d q contiene: %s\n", stCabecera.sector, (char *)stCabecera.buffer);
			}
			else
				printf("Lectura fallida\n");

			//break;
		}else if (strcmp(cp, "tiempoLectura") == 0)
		{
			cp = strtok(NULL, " ");
			stCabecera.sector = atoi(cp);
			if (stCabecera.sector > 0 )
			{
				//printf("\Modifica Tiempo de lectura\n");
				comandoInvalido = 1;
				stCabecera.ucType = TLECTURA;
				memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
				stCabecera.lPayload = strlen(stCabecera.buffer);

				if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
					log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar modificacion de tiempo de lectura");
				else
					log( "consolaLog.txt", "PPD", "INFO", "Envie modificacion de tiempo de lectura");

				printf("El nuevo tiempo de Lectura es: %f segundos\n", (float)stCabecera.sector /1000);
			}

		}else if (strcmp(cp, "tiempoEscritura") == 0)
		{
			cp = strtok(NULL, " ");
			stCabecera.sector = atoi(cp);
			if (stCabecera.sector > 0 )
			{
				//printf("\Modifica Tiempo de escritura\n");
				comandoInvalido = 1;
				stCabecera.ucType = TESCRITURA;

				memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
				stCabecera.lPayload = strlen(stCabecera.buffer);

				if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
					log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar modificacion de tiempo de escritura");
				else
					log( "consolaLog.txt", "PPD", "INFO", "Envie modificacion de tiempo de escritura");

				printf("El nuevo tiempo de escritura es: %f segundos\n", (float)stCabecera.sector /1000);
			}
		}

		if (comandoInvalido==0)
			printf("Comando Incorrecto. Ingrese help para ver los comandos disponibles.\n");

	}

	close(sockConsola);
	return 0;
}

void FinConsola(void)
{
	printf("\n");
	ST_NIPC	stCabecera;

	stCabecera.ucType = CERRADO;
	stCabecera.lPayload = 0;
	memset(stCabecera.buffer, 0, sizeof(ST_SECTOR));
	if(send(sockConsola, &stCabecera,sizeof(ST_NIPC), MSG_NOSIGNAL) < 0 )
		log( "consolaLog.txt", "PPD", "ERROR", "Error al enviar petición de Información de cabezal");
	else
		log( "consolaLog.txt", "PPD", "INFO", "Envie petición de Información de cabezal");

	close(sockConsola);
	exit(0);
}
